﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Pipes.Queries.Model.Query
{
  public class ReadStatement : IExpression, IStatement
  {
    public bool Deterministic { get { return false; } }
    public Pipes.Queries.MetaData.GeneralDataType InferredType { get; set; }
    private IList<SimpleDeclaration> _cols = new List<SimpleDeclaration>();
    private IList<IExpression> _groupBy = new List<IExpression>();
    private IList<OrderSpec> _orderBy = new List<OrderSpec>();
    private IList<Join> _source = new List<Join>();
    private IList<SimpleDeclaration> _vars = new List<SimpleDeclaration>();

    public IList<SimpleDeclaration> Columns
    {
      get
      {
        return _cols;
      }
    }
    public IList<IExpression> GroupBy 
    { 
      get 
      {
        return _groupBy;
      } 
    }
    public IExpression Having { get; set; }
    public ParseData MetaData { get; set; }
    public IList<OrderSpec> OrderBy 
    { 
      get 
      {
        return _orderBy;
      } 
    }
    public int RowLimit { get; set; }
    public int RowOffset { get; set; }
    public ResultScope Scope_Union { get; set; }
    public ResultScope Scope_Statement { get; set; }
    public IList<Join> Source 
    { 
      get 
      {
        return _source;
      } 
    }
    public IList<SimpleDeclaration> Vars
    {
      get
      {
        return _vars;
      }
    }
    public IExpression Where { get; set; }

    public ReadStatement()
    {
      this.InferredType = Pipes.Queries.MetaData.GeneralDataType.tuple;
      this.Scope_Union = ResultScope.All;
      this.Scope_Statement = ResultScope.All;
      this.RowLimit = int.MaxValue;
      this.RowOffset = 0;
    }

    public override string ToString()
    {
      var builder = new StringBuilder("SELECT ");

      for (var i = 0; i < _cols.Count; i++)
      {
        if (i > 0) builder.Append(", ");
        builder.Append(_cols[i].ToString());
      }
      for (var i = 0; i < _source.Count; i++)
      {
        if (i == 0) builder.Append(" FROM ");
        builder.Append(_source[i].ToString());
      }
      if (this.Where != null) 
      {
        builder.Append(" WHERE ");
        builder.Append(this.Where.ToString());
      }
      for (var i = 0; i < _groupBy.Count; i++)
      {
        if (i == 0)
        {
          builder.Append(" GROUP BY ");
        }
        else
        {
          builder.Append(", ");
        }
        builder.Append(_groupBy[i].ToString());
      }
      if (this.Having != null)
      {
        builder.Append(" HAVING ");
        builder.Append(this.Having.ToString());
      }
      for (var i = 0; i < _orderBy.Count; i++)
      {
        if (i == 0)
        {
          builder.Append(" ORDER BY ");
        }
        else
        {
          builder.Append(", ");
        }
        builder.Append(_orderBy[i].ToString());
      }

      return builder.ToString();
    }

    public void Visit(Parser.IQueryVisitor visitor)
    {
      visitor.Visit(this);
    }

    public object Evaluate()
    {
      throw new NotImplementedException();
    }
  }
}
